﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
using System.Reflection;
using System.IO;
using System.Drawing.Text;

namespace Walson.Windows.Forms
{
    /// <summary>
    /// 圆形罗盘
    /// </summary>
    public partial class RoundCompass : UserControl
    {

        private float _MarkerWidth = 2.0f;
        /// <summary>
        /// 标记宽度
        /// </summary>
        public float MarkerWidth
        {
            get => _MarkerWidth;
            set
            {
                _MarkerWidth = value;
                _Pen = new Pen(ForeColor, _MarkerWidth);
                this.Invalidate();
            }
        }

        /// <summary>
        /// 前景色
        /// </summary>
        public override Color ForeColor
        {
            get
            {
                return base.ForeColor;
            }
            set
            {
                base.ForeColor = value;
                _Pen = new Pen(value, _MarkerWidth);
                LoadResource();
                DrawElement();
                this.Invalidate();
            }

        }

        /// <summary>
        /// 背景色
        /// </summary>
        public override Color BackColor
        {
            get
            {
                return base.BackColor;
            }
            set
            {
                base.BackColor = value;
                DrawElement();
                this.Invalidate();
            }
        }

        private int _Heading;
        /// <summary>
        /// 当前的航向
        /// </summary>
        public int Heading
        {
            get
            {
                return _Heading;
            }
            set
            {
                while (_Heading > 360)
                    _Heading -= 360;
                while (_Heading < 0)
                    _Heading += 360;
                _Heading = value;
                this.Invalidate();
            }
        }

        private bool _CenterRotate;
        /// <summary>
        /// 是否中心旋转
        /// </summary>
        public bool CenterRotate
        {
            get
            {
                return _CenterRotate;
            }
            set
            {
                _CenterRotate = value;
                this.Invalidate();
            }
        }

        private int _ShortMarkerLength = 5;
        /// <summary>
        /// 短刻度的长度
        /// </summary>
        public int ShortMarkerLength
        {
            get
            {
                return _ShortMarkerLength;
            }
            set
            {
                _ShortMarkerLength = value;
                DrawElement();
                this.Invalidate();
            }
        }

        private int _LongMarkerLength = 10;
        /// <summary>
        /// 长刻度的长度
        /// </summary>
        public int LongMarkerLength
        {
            get
            {
                return _LongMarkerLength;
            }
            set
            {
                _LongMarkerLength = value;
                DrawElement();
                this.Invalidate();
            }
        }

        /// <summary>
        /// 字体
        /// </summary>
        public override Font Font
        {
            get
            {
                return base.Font;
            }
            set
            {
                base.Font = value;
                DrawElement();
                this.Invalidate();
            }
        }

        private Size _PlaneSize;
        private Size _OriginalSize;
        private Bitmap _Plane;
        private Bitmap _bmp;
        private Pen _Pen;
        private float _PlaneScaleFactor = 1.0f;

        private void LoadResource()
        {
            //Assembly myAssembly = Assembly.GetExecutingAssembly();
            //Stream myStream = myAssembly.GetManifestResourceStream("Walson.Resources.Plane.png");
            Bitmap bmp = global::Walson.Windows.Forms.Properties.Resources.Plane;
            Bitmap bmp2 = new Bitmap((int)(bmp.Width * _PlaneScaleFactor), (int)(bmp.Height * _PlaneScaleFactor));


            for (int i = 0; i < bmp.Width; i++)
                for (int j = 0; j < bmp.Height; j++)
                {
                    if (bmp.GetPixel(i, j).A != 0)
                        bmp.SetPixel(i, j, base.ForeColor);
                }

            using (Graphics g = Graphics.FromImage(bmp2))
            {
                g.ScaleTransform(_PlaneScaleFactor, _PlaneScaleFactor);
                g.DrawImage(bmp, 0, 0);
                g.ResetTransform();

            }

            _Plane = bmp2;
            _PlaneSize = bmp2.Size;
            _OriginalSize = bmp.Size;
        }



        private void DrawElement()
        {
            int max = Math.Max(this.Width, this.Height);
            int min = Math.Min(this.Width, this.Height);
            int r = -min / 2;
            Bitmap bmp = new Bitmap(min, min);
            using (Graphics g = Graphics.FromImage(bmp))
            {
                g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
                g.TextRenderingHint = TextRenderingHint.AntiAlias;
                g.TranslateTransform(min / 2f, min / 2f);
                g.Clear(this.BackColor);

                PointF[] line = new PointF[2];
                for (int i = 0; i < 60; i++)
                {
                    line[0] = new PointF(0, r + 10);

                    if (i % 5 == 0)
                    {
                        line[1] = new PointF(0, r + _LongMarkerLength + 10);
                        int angle = i * 6;
                        SizeF size = g.MeasureString(angle.ToString(), this.Font);
                        g.DrawString(angle.ToString(), this.Font, new SolidBrush(base.ForeColor), -size.Width / 2, r + _LongMarkerLength + 15);

                    }
                    else
                    {
                        line[1] = new PointF(0, r + _ShortMarkerLength + 10);
                    }
                    g.DrawLine(_Pen, line[0], line[1]);

                    g.RotateTransform(6);
                }
            }
            _bmp = bmp;
        }

        /// <summary>
        /// 圆形罗盘
        /// </summary>
        public RoundCompass()
        {
            InitializeComponent();

            _Pen = new Pen(base.ForeColor, MarkerWidth);
            this.DoubleBuffered = true;
            _PlaneScaleFactor = 1;

            this.DoubleBuffered = true;

            LoadResource();

            this.SizeChanged += new EventHandler(FlightCompass_SizeChanged);

            this.Size = new Size(90, 90);
            this.ForeColor = Color.White;
            this.BackColor = Color.FromArgb(16, 16, 49);

            DrawElement();
        }

        private void FlightCompass_SizeChanged(object sender, EventArgs e)
        {
            int min = Math.Min(this.Width, this.Height);
            int r = -min / 2;
            DrawElement();
            try
            {
                _PlaneScaleFactor = (float)((-r - 30.0) / _OriginalSize.Width);
            }
            catch (System.Exception)
            {
                _PlaneScaleFactor = 1f;
            }

            if (_PlaneScaleFactor <= 0)
                _PlaneScaleFactor = 1f;

            LoadResource();
            this.Invalidate();
        }

        /// <summary>
        /// 圆形罗盘
        /// </summary>
        public RoundCompass(IContainer container)
        {
            container.Add(this);

            InitializeComponent();

            _Pen = new Pen(base.ForeColor, MarkerWidth);
            this.DoubleBuffered = true;
            _PlaneScaleFactor = 1;

            this.DoubleBuffered = true;

            LoadResource();

            this.SizeChanged += new EventHandler(FlightCompass_SizeChanged);

            this.Size = new Size(90, 90);
            this.ForeColor = Color.White;
            this.BackColor = Color.FromArgb(16, 16, 49);

            DrawElement();
        }

        /// <summary>
        /// 绘制控件
        /// </summary>
        /// <param name="e">参数</param>
        protected override void OnPaint(PaintEventArgs e)
        {
            if (_bmp == null)
                return;

            int min = Math.Min(this.Width, this.Height);
            int max = Math.Max(this.Width, this.Height);
            int r = -min / 2;
            //int r = 0;

            using (Bitmap bmp = new Bitmap(this.Width, this.Height))
            {
                using (Graphics g = Graphics.FromImage(bmp))
                {
                    g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
                    g.TextRenderingHint = TextRenderingHint.AntiAlias;

                    g.Clear(BackColor);

                    SizeF fontSize = g.MeasureString("5", this.Font);

                    if (_CenterRotate)
                    {

                        g.TranslateTransform(this.Width / 2f, this.Height / 2f);

                        g.DrawImage(_bmp, -_bmp.Width / 2f, -_bmp.Height / 2f);

                        g.RotateTransform(_Heading);                        // 绘制三角形
                        PointF[] triangle = new PointF[4];
                        triangle[0] = new PointF(0, fontSize.Height + 20 + r + _LongMarkerLength);
                        triangle[1] = new PointF(-7, fontSize.Height + 30 + r + _LongMarkerLength);
                        triangle[2] = new PointF(7, fontSize.Height + 30 + r + _LongMarkerLength);
                        triangle[3] = new PointF(0, fontSize.Height + 20 + r + _LongMarkerLength);
                        //g.DrawLines(Pens.White, triangle);
                        g.FillPolygon(new SolidBrush(base.ForeColor), triangle);

                        g.DrawImage(_Plane, -_Plane.Width / 2f, -_Plane.Height / 2f);
                    }
                    else
                    {
                        g.TranslateTransform(this.Width / 2f, this.Height / 2f);

                        g.RotateTransform(-_Heading);

                        //g.DrawImage(_bmp, -_bmp.Width / 2, -_bmp.Height / 2);
                        PointF[] line = new PointF[2];
                        for (int i = 0; i < 60; i++)
                        {
                            line[0] = new PointF(0, r + 10);

                            if (i % 5 == 0)
                            {
                                line[1] = new PointF(0, r + _LongMarkerLength + 10);
                                int angle = i * 6;
                                SizeF size = g.MeasureString(angle.ToString(), this.Font);
                                g.DrawString(angle.ToString(), this.Font, new SolidBrush(base.ForeColor), -size.Width / 2, r + _LongMarkerLength + 15);

                            }
                            else
                            {
                                line[1] = new PointF(0, r + _ShortMarkerLength + 10);
                            }
                            g.DrawLine(_Pen, line[0], line[1]);

                            g.RotateTransform(6);
                        }




                        g.ResetTransform();
                        g.TranslateTransform(this.Width / 2f, this.Height / 2f);

                        // 绘制三角形
                        PointF[] triangle = new PointF[4];
                        triangle[0] = new PointF(0, fontSize.Height + 20 + r + _LongMarkerLength);
                        triangle[1] = new PointF(-7, fontSize.Height + 30 + r + _LongMarkerLength);
                        triangle[2] = new PointF(7, fontSize.Height + 30 + r + _LongMarkerLength);
                        triangle[3] = new PointF(0, fontSize.Height + 20 + r + _LongMarkerLength);
                        //g.DrawLines(Pens.White, triangle);
                        g.FillPolygon(new SolidBrush(base.ForeColor), triangle);

                        g.DrawImage(_Plane, -_Plane.Width / 2f, -_Plane.Height / 2f);
                    }

                    g.ResetTransform();
                }
                e.Graphics.DrawImage(bmp, 0, 0);
            }

            // 绘制圆角控件
            Rectangle rect = new Rectangle(0, 0, base.Width, base.Height);
            int radius = 50;
            System.Drawing.Drawing2D.GraphicsPath roundRect = new System.Drawing.Drawing2D.GraphicsPath();
            //顶端 
            roundRect.AddLine(rect.Left + radius - 1, rect.Top - 1, rect.Right - radius, rect.Top - 1);
            //右上角 
            roundRect.AddArc(rect.Right - radius, rect.Top - 1, radius, radius, 270, 90);
            //右边 
            roundRect.AddLine(rect.Right, rect.Top + radius, rect.Right, rect.Bottom - radius);
            //右下角
            roundRect.AddArc(rect.Right - radius, rect.Bottom - radius, radius, radius, 0, 90);
            //底边 
            roundRect.AddLine(rect.Right - radius, rect.Bottom, rect.Left + radius, rect.Bottom);
            //左下角 
            roundRect.AddArc(rect.Left - 1, rect.Bottom - radius, radius, radius, 90, 90);
            //左边 
            roundRect.AddLine(rect.Left - 1, rect.Top + radius, rect.Left - 1, rect.Bottom - radius);
            //左上角 
            roundRect.AddArc(rect.Left - 1, rect.Top - 1, radius, radius, 180, 90);
            this.Region = new Region(roundRect);

            base.OnPaint(e);
        }
    }


}
